package Game.GameStates 
{
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2Body;
	import Common.GamePhysics;
	import Common.Input;
	import Common.Managers.SwfManager;
	import Common.Utils;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.filters.ColorMatrixFilter;
	import flash.filters.GlowFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Point;
	import flash.media.Camera;
	import flash.net.FileReference;
	import flash.text.TextField;
	import flash.utils.ByteArray;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
	import Game.GameCamera;
	import Game.GameElements.Background;
	import Game.GameElements.BattleTower;
	import Game.GameElements.GameObject;
	import Game.GameElements.Tank;
	import Game.GameElements.Wall;
	import Game.Windows.LoadingWindow;
	import Game.World;
	/**
	 * ...
	 * @author Yevgeniy Logachev
	 */
	public class EditorState extends BaseState
	{
		[Embed(source="../../../res/swf/levelEditorPanel.swf", symbol="toolsPanel")]
		public static var ToolsPanelClass:Class;
		
		private var m_toolsPanel:MovieClip 			= null;
		
		private var m_previewBack:Sprite 			= null;
		private var m_previewFore:Sprite 			= null;
		private var m_previewItems:Sprite 			= null;
		private var m_sliderHorizontal:Sprite 		= null;
		private var m_sliderVertical:Sprite 		= null;
		private var m_scrollHorizontal:Sprite 		= null;
		private var m_scrollVertical:Sprite 		= null;
		private var m_checkBoxScroll:MovieClip 		= null;
		private var m_checkBoxIsPhysic:MovieClip 	= null;
		private var m_checkBoxIsStatic:MovieClip 	= null;
		private var m_checkBoxIsFreeze:MovieClip 	= null;
		
		private var m_previewSize:int				= 50;
		
		private var m_backIndex:int 				= 0;
		private var m_foreIndex:int 				= 0;
		private var m_itemsIndex:int 				= 0;
		
		private var m_previewElement:GameObject 		= null;
		private var m_selectedFilter:ColorMatrixFilter 	= null;
		
		private var m_textFieldPosX:TextField		= null;
		private var m_textFieldPosY:TextField		= null;		
		
		private var m_scrollMargins:Number 			= 100;
		private var m_mouseOldX:Number 				= 0;
		private var m_mouseOldY:Number 				= 0;
		private var m_isScroll:Boolean 				= false;
		
		public function EditorState() 
		{
			super();
			
			LoadingWindow.show = true;
			// Load all resources
			SwfManager.instance.loadAll([Tank.m_swfPath, Wall.m_swfPath, Background.m_swfPath, BattleTower.m_swfPath], onResourceLoaded);
		}
		
		public function onResourceLoaded():void
		{
			LoadingWindow.show = false;

			m_toolsPanel = new ToolsPanelClass();
			m_toolsPanel.gotoAndStop("openTools");
			createElements();
			
			Main.mainSprite.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp, false, 0, true);
			Main.mainSprite.stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown, false, 0, true);
			
			updatePreview();
			
			Main.mainSprite.stage.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
			Main.mainSprite.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove, false, 0, true);
			//Main.mainSprite.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove, false, 0, true);
			Main.mainSprite.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown, false, 0, true);
			Main.mainSprite.stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel, false, 0, true);
			//m_toolsPanel.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove, false, 0, true);
			
			World.instance.initialize(0, null, true);
			
			Main.mainSprite.stage.addChild(m_toolsPanel);
			Main.mainSprite.stage.addEventListener(Event.RESIZE, onResize);
			
			var matrix:Array = new Array();
			matrix = matrix.concat([0, 0, 0, 0, 0]); // red
			matrix = matrix.concat([0, 1, 0, 0, 0]); // green
			matrix = matrix.concat([0, 0, 0, 0, 0]); // blue
			matrix = matrix.concat([0, 0, 0, 0.5, 0]); // alpha
			m_selectedFilter = new ColorMatrixFilter(matrix);
			
			GamePhysics.instance.debugDraw();
			
			m_isInit = true;
		}
		
		public function createElements():void
		{
			m_previewBack = m_toolsPanel.getChildByName("BackPreview") as Sprite;
			m_previewFore = m_toolsPanel.getChildByName("ForePreview") as Sprite;
			m_previewItems = m_toolsPanel.getChildByName("ItemsPreview") as Sprite;		
			
			//m_scrollHorizontal = m_toolsPanel.getChildByName("scrollHorizontal") as Sprite;
			//m_scrollVertical = m_toolsPanel.getChildByName("scrollVertical") as Sprite;
			//m_sliderHorizontal = m_scrollHorizontal.getChildByName("sliderHorizontal") as Sprite;
			//m_sliderVertical = m_scrollVertical.getChildByName("sliderVertical") as Sprite;
			m_checkBoxScroll = m_toolsPanel.getChildByName("checkBoxScroll") as MovieClip;
			if (m_checkBoxScroll != null)
			{
				m_checkBoxScroll.gotoAndStop((m_isScroll) ? "on" : "off");
			}
			
			m_checkBoxIsPhysic = m_toolsPanel.getChildByName("isPhysic") as MovieClip;
			if (m_checkBoxIsPhysic != null)
			{
				m_checkBoxIsPhysic.gotoAndStop((isPhysic) ? "on" : "off");
			}
			
			m_checkBoxIsStatic = m_toolsPanel.getChildByName("isStatic") as MovieClip;
			if (m_checkBoxIsStatic != null)
			{
				m_checkBoxIsStatic.gotoAndStop((isStatic) ? "on" : "off");
			}
			
			m_checkBoxIsFreeze = m_toolsPanel.getChildByName("isFreeze") as MovieClip;
			if (m_checkBoxIsFreeze != null)
			{
				m_checkBoxIsFreeze.gotoAndStop((isFreeze) ? "on" : "off");
			}
						
			var posPanel:Sprite = m_toolsPanel.getChildByName("positionPanel") as Sprite;
			if (posPanel != null)
			{
				m_textFieldPosX = posPanel.getChildByName("posX") as TextField;
				m_textFieldPosY = posPanel.getChildByName("posY") as TextField;
			}
		}
		
		public function updatePreview():void
		{
			var object:GameObject;
			if (m_previewBack != null)
			{
				while (m_previewBack.numChildren) m_previewBack.removeChildAt(0);
				object = new Background(0, 0, m_backIndex);//Wall(0, 0, m_backIndex, false);
				GameObject.gameObjects.splice(GameObject.gameObjects.indexOf(object), 1);
				object.scaleX = 64.0 / object.width;
				object.scaleY = 64.0 / object.height;
				World.instance.backgroundLayer.removeChild(object);
				m_previewBack.addChild(object);
			}	
			if (m_previewItems != null)
			{
				while (m_previewItems.numChildren) m_previewItems.removeChildAt(0);
				object = new BattleTower(0, 0, 0);//Wall(0, 0, m_backIndex, false);
				GameObject.gameObjects.splice(GameObject.gameObjects.indexOf(object), 1);
				object.destroyPhysicalObject();
				object.scaleX = 64.0 / object.width;
				object.scaleY = 64.0 / object.height;
				World.instance.objectLayer.removeChild(object);
				m_previewItems.addChild(object);
			}
			if (m_previewFore != null)
			{
				while (m_previewFore.numChildren) m_previewFore.removeChildAt(0);
				object = new Wall(0, 0, 0, m_foreIndex, false, false);//Wall(0, 0, m_backIndex, false);
				GameObject.gameObjects.splice(GameObject.gameObjects.indexOf(object), 1);
				object.scaleX = 64.0 / object.width;
				object.scaleY = 64.0 / object.height;
				World.instance.foregroundLayer.removeChild(object);
				m_previewFore.addChild(object);
			}
		}
		
		public function onResize(e:Event):void
		{
			var point:Point = new Point(0, 0);
			Main.mainSprite.globalToLocal(point);
			Main.mainSprite.x = point.x;
			Main.mainSprite.y = point.y;
			
			var dx:Number = Settings.screenWidth - Main.mainSprite.stage.stageWidth;
			var dy:Number = Settings.screenHeight - Main.mainSprite.stage.stageHeight;
			
			Settings.screenWidth = Main.mainSprite.stage.stageWidth;
			Settings.screenHeight = Main.mainSprite.stage.stageHeight;
			
			m_toolsPanel.x += dx / 2;
			m_toolsPanel.y += dy / 2;
		}
		
		public function onClick(e:MouseEvent):void
		{
			var buttonName:String = e.target.name;
			
			switch(buttonName)
			{
				case "buttonBackRight":
					if (++m_backIndex > Background.m_BackgroundTypes.length - 1)
					{
						m_backIndex = 0;
					}
				break;
				
				case "buttonBackLeft":
					if (--m_backIndex < 0)
					{
						m_backIndex = Background.m_BackgroundTypes.length - 1;
					}
				break;
				
				case "buttonForeRight":
					if (++m_foreIndex > Wall.m_wallTypes.length - 1)
					{
						m_foreIndex = 0;
					}
				break;
				
				case "buttonForeLeft":
					if (--m_foreIndex < 0)
					{
						m_foreIndex = Wall.m_wallTypes.length - 1;
					}
				break;
				
				case "buttonItemsRight":
					if (++m_itemsIndex > BattleTower.m_basisType.length - 1)
					{
						m_itemsIndex = 0;
					}
				break;
				
				case "buttonItemsLeft":
					if (--m_itemsIndex < 0)
					{
						m_itemsIndex = BattleTower.m_basisType.length - 1;
					}
				break;
				
				case "buttonSave":
					World.instance.saveLevel();
				break;
				
				case "buttonOpen":
					World.instance.loadLevel();
				break;
				
				case "buttonCloseTools":
				case "buttonOpenTools":
					openCloseTools();
				break;
				
				case "checkBoxScroll":
					m_isScroll = !m_isScroll;
					if (m_checkBoxScroll != null)
					{
						m_checkBoxScroll.gotoAndStop((m_isScroll) ? "on" : "off");
					}
				break;
				
				case "isPhysic":
					if (m_previewElement != null)
					{
						isPhysic = !isPhysic;
						(isPhysic) ? m_previewElement.createPhysicalObject(isStatic) : m_previewElement.destroyPhysicalObject();
					}
				break;
				
				case "isStatic":
					if (m_previewElement != null && m_previewElement.physicalObject != null)
					{
						isStatic = !isStatic;
						m_previewElement.physicalObject.SetType((isStatic) ? b2Body.b2_staticBody : b2Body.b2_dynamicBody);
					}
				break;
				
				case "isFreeze":
					if (m_previewElement != null)
					{
						m_previewElement.isFreeze = !m_previewElement.isFreeze;
					}
				break;
				
				case "rotateLeft":
					if (m_previewElement is GameObject)
					{
						m_previewElement.Rotation -= 5;
					}
				break;
				
				case "rotateRight":
					if (m_previewElement is GameObject)
					{
						m_previewElement.Rotation = m_previewElement.rotation + 5;
					}
				break;
				
				case "buttonItems":
					m_toolsPanel.gotoAndStop("openItems");
					createElements();
				break;
				
				case "buttonReturn":
					m_toolsPanel.gotoAndStop("openTools");
					createElements();
				break;
				
				case "buttonProps":
					m_toolsPanel.gotoAndStop("openProperties");
					createElements();
				break;
			}
			
			updateProperties();
			updatePreview();
		}
		
		public function openCloseTools():void
		{
			if (m_toolsPanel.currentFrameLabel == "closeTools")
			{
				m_toolsPanel.gotoAndStop("openTools");
			}
			else
			{
				m_toolsPanel.gotoAndStop("closeTools");
			}
			createElements();
		}
		
		public function onMouseUp(e:MouseEvent):void
		{
			//if (m_previewElement != null)
			//{		
				//m_previewElement.stopDrag();
			//}
		}
		
		public function onMouseDown(e:MouseEvent):void
		{
			if (m_isScroll)
			{
				return;
			}
			if (e.target == Main.mainSprite.stage)
			{
				if (m_previewElement != null)
				{
					clearPreview();
					return;
				}
			}
			else if (m_previewBack != null && m_previewBack.numChildren > 0 && e.target.parent == (m_previewBack.getChildAt(0) as GameObject))
			{
				if (m_previewElement != null)
				{
					clearPreview();
				}				
				m_previewElement = new Background(e.stageX, e.stageY, m_backIndex);
				m_previewElement.filters = [m_selectedFilter];
				updateCursorPos(m_previewElement.x, m_previewElement.y);
				return;
			}
			else if (m_previewFore != null && m_previewFore.numChildren > 0 && e.target.parent == (m_previewFore.getChildAt(0) as GameObject))
			{
				if (m_previewElement != null)
				{
					clearPreview();
				}				
				m_previewElement = new Wall(e.stageX, e.stageY, 0, m_foreIndex, false);
				m_previewElement.filters = [m_selectedFilter];
				updateCursorPos(m_previewElement.x, m_previewElement.y);
				return;
			}
			else if (m_previewItems != null && m_previewItems.numChildren > 0 && e.target.parent == (m_previewItems.getChildAt(0) as GameObject))
			{
				if (m_previewElement != null)
				{
					clearPreview();
				}				
				m_previewElement = new BattleTower(e.stageX, e.stageY, 0, m_itemsIndex, false, false);
				m_previewElement.filters = [m_selectedFilter];
				updateCursorPos(m_previewElement.x, m_previewElement.y);
				return;
			}
						
			for each(var object:GameObject in GameObject.gameObjects)
			{
				if ((e.target.parent is GameObject) && (e.target.parent == object))
				{
					if (m_previewElement != null)
					{
						clearPreview();
					}
					m_previewElement = object;
					m_previewElement.filters = [m_selectedFilter];
					updateCursorPos(m_previewElement.x, m_previewElement.y);
					updateProperties();
					return;
				}
			}
		}
		
		public function updateProperties():void
		{
			if (m_previewElement is GameObject)
			{
				isPhysic = (m_previewElement.physicalObject != null) ? true : false;
				
				isStatic = (m_previewElement.physicalObject != null && m_previewElement.physicalObject.GetType() == b2Body.b2_staticBody);
				
				isFreeze = m_previewElement.isFreeze;
			}
		}
		
		public function updateCursorPos(x:int, y:int):void
		{
			m_textFieldPosX.text = x.toString();
			m_textFieldPosY.text = y.toString();
		}
		
		public function clearPreview():void
		{
			m_previewElement.filters = [];
			m_previewElement = null;
		}
		
		public function onMouseMove(e:MouseEvent):void
		{
			var dx:Number = e.stageX - m_mouseOldX;
			var dy:Number = e.stageY - m_mouseOldY;
			m_mouseOldX = e.stageX;
			m_mouseOldY = e.stageY;
			
			if (e.buttonDown == true && m_isScroll)
			{
				/*m_sliderHorizontal.x += dx;
				if (m_sliderHorizontal.x < -m_scrollHorizontal.width / 2)
				{
					m_sliderHorizontal.x = -m_scrollHorizontal.width / 2;
				}
				else if (m_sliderHorizontal.x > m_scrollHorizontal.width / 2 - m_sliderHorizontal.width)
				{
					m_sliderHorizontal.x = m_scrollHorizontal.width / 2 - m_sliderHorizontal.width;
				}
				else
				{				
					var posx:Number = (m_sliderHorizontal.x / (m_scrollHorizontal.width / 2)) * (World.instance.getWidth() / 2);
					var posy:Number = Main.mainSprite.y;
				
					GameCamera.instance.scroll(posx, posy);
				}*/
				
				//GameCamera.instance.scroll(Main.mainSprite.localToGlobal(new Point(e.stageX, e.stageY)).x, Main.mainSprite.localToGlobal(new Point(e.stageX, e.stageY)).y);//
				GameCamera.instance.moveTo(dx, dy);
			}
			else if (m_previewElement != null && e.buttonDown == true && !m_previewElement.isFreeze && e.target != m_toolsPanel && e.target.parent != m_toolsPanel)
			{
				if (m_previewElement.physicalObject != null)
				{
					var vec:b2Vec2 = new b2Vec2(int((e.stageX - Main.mainSprite.x) / World.instance.scaleX) / GamePhysics.instance.physicalScale, 
												int((e.stageY - Main.mainSprite.y) / World.instance.scaleY) / GamePhysics.instance.physicalScale);
					m_previewElement.physicalObject.SetPosition(vec);
					m_previewElement.physicalObject.SetAwake(true);
				}
				else
				{		
					m_previewElement.x = int((e.stageX - Main.mainSprite.x) / World.instance.scaleX);
					m_previewElement.y = int((e.stageY - Main.mainSprite.y) / World.instance.scaleY);
				}
				
				updateCursorPos(m_previewElement.x, m_previewElement.y);
			}
			else if (m_previewElement == null)
			{
				updateCursorPos((e.stageX + World.instance.x) / World.instance.scaleX, (e.stageY + World.instance.y) / World.instance.scaleY);
			}
		}
		
		public function onMouseWheel(e:MouseEvent):void
		{
			(e.delta > 0) ? World.instance.zoomIn() : World.instance.zoomOut();
			GamePhysics.instance.setDebugScale(World.instance.scaleX);
		}
		
		public function onKeyDown(e:KeyboardEvent):void
		{
			switch(e.keyCode)
			{
				case Input.KEY_NUM_PLUS:
					World.instance.zoomIn();
				break;
				
				case Input.KEY_NUM_MINUS:
					World.instance.zoomOut();
				break;
				
				case Input.KEY_NUM_STAR:
					World.instance.zoom100();
				break;
				
				case Input.KEY_Q:
					m_isScroll = !m_isScroll;
					if (m_checkBoxScroll != null)
					{
						m_checkBoxScroll.gotoAndStop((m_isScroll) ? "on" : "off");
					}
				break;
				
				case Input.KEY_W:
					openCloseTools();
				break;
				
				case Input.KEY_P:
					GamePhysics.instance.enableDebug = !GamePhysics.instance.enableDebug;
				break;
			}
			
			if (m_previewElement == null) return;
			
			switch(e.keyCode)
			{
				case Input.KEY_LEFT:
					if (m_previewElement.physicalObject != null)
					{
						m_previewElement.physicalObject.SetPosition(new b2Vec2(m_previewElement.physicalObject.GetPosition().x - 1 / GamePhysics.instance.physicalScale, m_previewElement.physicalObject.GetPosition().y));
					}
					else
					{
						m_previewElement.x--;
					}
				break;
				
				case Input.KEY_RIGHT:
					if (m_previewElement.physicalObject != null)
					{
						m_previewElement.physicalObject.SetPosition(new b2Vec2(m_previewElement.physicalObject.GetPosition().x + 1 / GamePhysics.instance.physicalScale, m_previewElement.physicalObject.GetPosition().y));
					}
					else
					{
						m_previewElement.x++;
					}
				break;
				
				case Input.KEY_UP:
					if (m_previewElement.physicalObject != null)
					{
						m_previewElement.physicalObject.SetPosition(new b2Vec2(m_previewElement.physicalObject.GetPosition().x, m_previewElement.physicalObject.GetPosition().y - 1 / GamePhysics.instance.physicalScale));
					}
					else
					{
						m_previewElement.y--;
					}
				break;
				
				case Input.KEY_DOWN:
					if (m_previewElement.physicalObject != null)
					{
						m_previewElement.physicalObject.SetPosition(new b2Vec2(m_previewElement.physicalObject.GetPosition().x, m_previewElement.physicalObject.GetPosition().y + 1 / GamePhysics.instance.physicalScale));
					}
					else
					{
						m_previewElement.y++;
					}
				break;
				
				case Input.KEY_DELETE:
					m_previewElement.release();
				break;
				
				case Input.KEY_ESC:
					clearPreview();
				break;
			}
			
			if (m_previewElement.physicalObject != null)
			{
				m_previewElement.physicalObject.SetAwake(true);
			}
			
			updateCursorPos(m_previewElement.x, m_previewElement.y);
		}
		
		public function updateScrollBar():void
		{
			/*if (m_sliderHorizontal != null && m_scrollHorizontal != null && World.instance.getWidth() != 0 && !m_isScroll)
			{
				//m_sliderHorizontal.width = m_scrollHorizontal.width * (Settings.screenWidth / World.instance.backgroundLayer.width);
				m_sliderHorizontal.x = (Main.mainSprite.x / (World.instance.getWidth() / 2)) * (m_scrollHorizontal.width / 2);
				if (m_sliderHorizontal.x < -m_scrollHorizontal.width / 2)
				{
					m_sliderHorizontal.x = -m_scrollHorizontal.width / 2;
					var posx:Number = (m_sliderHorizontal.x / (m_scrollHorizontal.width / 2)) * (World.instance.getWidth() / 2);
					var posy:Number = Main.mainSprite.y;
				
					GameCamera.instance.scroll(posx, posy);
				}
				else if (m_sliderHorizontal.x > m_scrollHorizontal.width / 2 - m_sliderHorizontal.width)
				{
					m_sliderHorizontal.x = m_scrollHorizontal.width / 2 - m_sliderHorizontal.width;
					var posx:Number = (m_sliderHorizontal.x / (m_scrollHorizontal.width / 2)) * (World.instance.getWidth() / 2);
					var posy:Number = Main.mainSprite.y;
				
					GameCamera.instance.scroll(posx, posy);
				}
			}*/
			
			if (m_sliderVertical != null && m_scrollVertical != null && Main.mainSprite.height != 0)
			{
				//m_sliderVertical.height = m_sliderVertical.height * (Settings.screenHeight / Main.mainSprite.height);
				//m_sliderVertical.y = -m_sliderVertical.height / 2;
			}
		}
		
		override public function update():void
		{
			//updateScrollBar();
						
			GamePhysics.instance.physicalWorld.Step(1.0 / 30.0, 10, 10);
			GamePhysics.instance.physicalWorld.ClearForces();
			
			if (GamePhysics.instance.enableDebug)
			{
				GamePhysics.instance.physicalWorld.DrawDebugData();
			}
			
			// Update screen object to be equal physical object     
			for(var body:b2Body = GamePhysics.instance.physicalWorld.GetBodyList(); body; body = body.GetNext())
			{
				if (!(body.GetUserData() is DisplayObject))
				{
					continue;
				}
				
				body.GetUserData().x = int(body.GetPosition().x * GamePhysics.instance.physicalScale);
				body.GetUserData().y = int(body.GetPosition().y * GamePhysics.instance.physicalScale);
				
				body.GetUserData().rotation = body.GetAngle() * (180.0 / Math.PI);
			}
		}
		
		public function get isPhysic():Boolean
		{
			if (m_checkBoxIsPhysic != null)
			{
				return (m_checkBoxIsPhysic.currentFrameLabel == "on") ? true : false;
			}
			
			return false;
		}
		
		public function set isPhysic(value:Boolean):void
		{
			if (m_checkBoxIsPhysic != null)
			{
				m_checkBoxIsPhysic.gotoAndStop((value) ? "on" : "off");
			}
		}
		
		public function get isStatic():Boolean
		{
			if (m_checkBoxIsStatic != null)
			{
				return (m_checkBoxIsStatic.currentFrameLabel == "on") ? true : false;
			}
			
			return false;
		}
		
		public function set isStatic(value:Boolean):void
		{
			if (m_checkBoxIsStatic != null)
			{
				m_checkBoxIsStatic.gotoAndStop((value) ? "on" : "off");
			}
		}
		
		public function get isFreeze():Boolean
		{
			if (m_checkBoxIsFreeze != null)
			{
				return (m_checkBoxIsFreeze.currentFrameLabel == "on") ? true : false;
			}
			
			return false;
		}
		
		public function set isFreeze(value:Boolean):void
		{
			if (m_checkBoxIsFreeze != null)
			{
				m_checkBoxIsFreeze.gotoAndStop((value) ? "on" : "off");
			}
		}
	}

}